package com.aspira.algorithm;

import com.alibaba.fastjson.JSON;
import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.SingleKeyDatabaseShardingAlgorithm;
import com.google.common.collect.Range;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.LinkedHashSet;

public class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Integer> {
    private static final Logger log = LoggerFactory.getLogger(ModuloDatabaseShardingAlgorithm.class);

    @Override
    public String doEqualSharding(Collection<String> databases, ShardingValue<Integer> shardingValue) {
        for (String each : databases) {
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }

        log.info("collection:" + JSON.toJSONString(databases) + ",preciseShardingValue:" + JSON.toJSONString(shardingValue));
        throw new IllegalArgumentException();
    }

    @Override
    public Collection<String> doInSharding(Collection<String> databaseNames, ShardingValue<Integer> shardingValue) {
        log.info("collection:" + JSON.toJSONString(databaseNames) + ",preciseShardingValue:" + JSON.toJSONString(shardingValue));
        Collection<String> result = new LinkedHashSet<>(databaseNames.size());
        for (Integer value : shardingValue.getValues()) {
            for (String databaseName : databaseNames) {
                if (databaseName.endsWith(value % 2 + "")) {
                    result.add(databaseName);
                }
            }
        }

        return result;
    }

    @Override
    public Collection<String> doBetweenSharding(Collection<String> databaseNames, ShardingValue<Integer> shardingValue) {
        log.info("collection:" + JSON.toJSONString(databaseNames) + ",preciseShardingValue:" + JSON.toJSONString(shardingValue));
        Collection<String> result = new LinkedHashSet<>(databaseNames.size());
        Range<Integer> valueRange = shardingValue.getValueRange();
        for (Integer i = valueRange.lowerEndpoint(); i <= valueRange.upperEndpoint(); i++) {
            for (String datasourceName : databaseNames) {
                if (datasourceName.endsWith(i % 2 + "")) {
                    result.add(datasourceName);
                }
            }
        }

        return result;
    }
}
